﻿using System;
using System.Globalization;
using System.IO;
using System.Threading;
using log4net;

namespace HiTeachers.Utilities
{
    public static class Logger
    {
        private const string LoggerName = "HiTeachers";
        private static readonly ILog FrameworkLogger;
        private static readonly string LogPath;

        static Logger()
        {
            string configPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "configs/log4net.config");
            log4net.Config.XmlConfigurator.Configure(new FileInfo(configPath));
            FrameworkLogger = LogManager.GetLogger(LoggerName);
            LogPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
        }

        #region GetLogger wrappers
        public static ILog GetLogger(string name)
        {
            return LogManager.GetLogger(name);
        }

        public static ILog GetLogger(string repository, string name)
        {
            return LogManager.GetLogger(repository, name);
        }

        public static ILog GetLogger(System.Reflection.Assembly assembly, string name)
        {
            return LogManager.GetLogger(assembly, name);
        }

        public static ILog GetLogger(System.Reflection.Assembly assembly, Type type)
        {
            return LogManager.GetLogger(assembly, type);
        }

        public static ILog GetLogger(Type type)
        {
            return LogManager.GetLogger(type);
        }

        public static ILog GetLogger(string repository, Type type)
        {
            return LogManager.GetLogger(repository, type);
        }
        #endregion

        private static string FormatMessage(string message)
        {
            string username = string.Empty;
            if (Thread.CurrentPrincipal != null)
            {
                username = Thread.CurrentPrincipal.Identity.Name;
            }
            else
            {
                if (System.Web.HttpContext.Current != null &&
                    System.Web.HttpContext.Current.User != null)
                {
                    username = System.Web.HttpContext.Current.User.Identity.Name;
                }
            }

            if (string.IsNullOrEmpty(username))
                return message;
            return string.Format("[{0}] {1}", username, message);
        }

        #region Debug wrapper methods
        public static bool IsDebugEnabled
        {
            get { return FrameworkLogger.IsDebugEnabled; }
        }

        public static void Debug(string message)
        {
            FrameworkLogger.Debug(FormatMessage(message));
        }

        public static void Debug(string message, Exception ex)
        {
            FrameworkLogger.Debug(FormatMessage(message), ex);
        }

        public static void Debug(string format, params object[] args)
        {
            if (args != null && args.Length > 0)
                FrameworkLogger.Debug(FormatMessage(String.Format(format, args)));
            else
                FrameworkLogger.Debug(FormatMessage(format));
        }
        #endregion

        #region Info wrapper methods
        public static bool IsInfoEnabled
        {
            get { return FrameworkLogger.IsInfoEnabled; }
        }

        public static void Info(string message)
        {
            FrameworkLogger.Info(FormatMessage(message));
        }

        public static void Info(string message, Exception ex)
        {
            FrameworkLogger.Info(FormatMessage(message), ex);
        }

        public static void Info(string format, params object[] args)
        {
            if (args != null && args.Length > 0)
                FrameworkLogger.Info(FormatMessage(String.Format(format, args)));
            else
                FrameworkLogger.Info(FormatMessage(format));
        }
        #endregion

        #region Error wrapper methods
        public static bool IsErrorEnabled
        {
            get { return FrameworkLogger.IsErrorEnabled; }
        }

        public static void Error(string message)
        {
            FrameworkLogger.Error(FormatMessage(message));
        }

        public static void Error(Exception e)
        {
            FrameworkLogger.Error(e);
        }

        public static void Error(string message, Exception ex)
        {
            FrameworkLogger.Error(FormatMessage(message), ex);
        }

        public static void Error(string format, params object[] args)
        {
            if (args != null && args.Length > 0)
                FrameworkLogger.Error(FormatMessage(String.Format(format, args)));
            else
                FrameworkLogger.Error(FormatMessage(format));
        }
        #endregion

        #region Warn wrapper methods
        public static bool IsWarnEnabled
        {
            get { return FrameworkLogger.IsWarnEnabled; }
        }

        public static void Warn(string message)
        {
            FrameworkLogger.Warn(FormatMessage(message));
        }

        public static void Warn(string message, Exception ex)
        {
            FrameworkLogger.Warn(FormatMessage(message), ex);
        }

        public static void Warn(string format, params object[] args)
        {
            if (args != null && args.Length > 0)
                FrameworkLogger.Warn(FormatMessage(String.Format(format, args)));
            else
                FrameworkLogger.Warn(FormatMessage(format));
        }
        #endregion

        #region Fatal wrapper methods
        public static bool IsFatalEnabled
        {
            get { return FrameworkLogger.IsFatalEnabled; }
        }

        public static void Fatal(string message)
        {
            FrameworkLogger.Fatal(FormatMessage(message));
        }

        public static void Fatal(string message, Exception ex)
        {
            FrameworkLogger.Fatal(FormatMessage(message), ex);
        }

        public static void Fatal(string format, params object[] args)
        {
            if (args != null && args.Length > 0)
                FrameworkLogger.Fatal(FormatMessage(String.Format(format, args)));
            else
                FrameworkLogger.Fatal(FormatMessage(format));
        }
        #endregion

        #region per user
        public static void PrivateDebug(string message, params object[] args)
        {
            PrivateDebug(string.Format(message, args));
        }

        private static readonly object Sync = new object();
        public static void PrivateDebug(string message)
        {
            lock (Sync)
            {
                File.AppendAllText(
                    Path.Combine(LogPath,
                        string.Format("{0}-{1}-debug.txt",
                            Thread.CurrentPrincipal.Identity.Name,
                            DateTime.Now.ToString("ddMMyy", CultureInfo.InvariantCulture))),
                    string.Format("{0} [{1}] [DEBUG] {2}\r\n",
                        DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss", CultureInfo.InvariantCulture),
                        Thread.CurrentThread.ManagedThreadId,
                        message));
            }
        }

        private static readonly object Sync1 = new object();
        public static void PrivateInfo(string message)
        {
            lock (Sync1)
            {
                File.AppendAllText(
                    Path.Combine(LogPath,
                        string.Format("{0}-{1}-info.txt",
                            Thread.CurrentPrincipal.Identity.Name,
                            DateTime.Now.ToString("ddMMyy", CultureInfo.InvariantCulture))),
                    string.Format("{0} [{1}] [INFO] {2}\r\n",
                        DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss", CultureInfo.InvariantCulture),
                        Thread.CurrentThread.ManagedThreadId,
                        message));
            }
        }
        #endregion
    }
}
